home *** CD-ROM | disk | FTP | other *** search
/ Universe of 3,000 Games / Universe of 3000 Game Patches.dmg / utils / src / lookup.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  8KB  |  352 lines

  1. /*
  2.  *    lookup.c
  3.  *
  4.  *
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <memory.h>
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <assert.h>
  15. #ifdef unix
  16. #include <unistd.h>
  17. /* #include <strerror.h>*/
  18. #define strnicmp  strncasecmp
  19. #else
  20. #include <io.h>
  21. #include <dir.h>
  22. #endif
  23.  
  24. #include "rockridg.h"
  25. #include "datadef.h"
  26.  
  27. #ifndef O_BINARY
  28. #define O_BINARY 0
  29. #endif
  30.  
  31. static void Read(int fd, void *buf, int n, int swap);
  32. #if 0
  33. static void _Read(int fd, void *buf, int n, int swap, int line, char *file);
  34. #define  Read(fd, buf, n, swap) _Read((fd), (buf), (n), (swap), __LINE__, __FILE__)
  35. #endif
  36.  
  37. #ifdef unix
  38. static const char datafile[] = "lookup.dat";
  39. #else
  40. static const char datafile[] = "/utils/lookup.dat";
  41. #endif
  42. char datafileroot[30];
  43. static char word[256];
  44. static struct file_header hdr;
  45. static long rehash6;
  46. static long rehash16;
  47. static int fd;
  48.  
  49. static long
  50. hash2(const unsigned char *s) {
  51.   unsigned long h, g, r;
  52.   int c;
  53.   int i;
  54.  
  55.   r = h = ((long) s[0] << 16) + (s[1] << 8);
  56.   for (i = 0; s[i] != 0; ++i) {
  57.       h += ((long) s[i] << i) + s[i];
  58.       h ^= h >> i;
  59.   }
  60.   while ((c = *s++) != '\0') {
  61.       h <<= 4;
  62.       h += c;
  63.       g = h & 0xf0000000;
  64.       h ^= g;
  65.       h ^= (g >> 24);
  66.       r ^= h;
  67.   }
  68.   rehash6 = r % 61;
  69.   rehash16 = r % 65521;
  70.   return h % hdr.hash_prime;
  71. }
  72.  
  73. static int
  74. search_file(const char *filename) {
  75.     FILE *fp;
  76.     int rv;
  77.     static char line[257];
  78.     char *s;
  79.     int lc, uc, len;
  80.  
  81.  
  82. /*    fprintf(stderr, "searching file %s\n", filename); */
  83.  
  84.     lc = *word;
  85.     if (islower(lc)) {
  86.         uc = lc + 'A' - 'a';
  87.     } else {
  88.         uc = lc;
  89.     }
  90.     len = strlen(word);
  91.     if ((fp = fopen(filename, "rt")) == NULL) {
  92.         fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
  93.         return 0;
  94.     }
  95.     rv = 0;
  96.     while (fgets(line, 256, fp) != NULL) {
  97.     line[255] = '\n';
  98.     line[256] = '\0';
  99.         for (s = line; *s != 0; ++s) {
  100.             if (*s == lc || (*s == uc && isupper(*s))) {
  101.                 if (strnicmp(s, word, len) == 0) {
  102.                     ++rv;
  103.                     printf("%s: %s", filename, line);
  104.             break;
  105.                 }
  106.             }
  107.         }
  108.     }
  109.     fclose(fp);
  110.     return rv;
  111. }
  112.  
  113. static char *
  114. lookup_dir(int n) {
  115.     static char path[1024];
  116.     unsigned char buf[300];
  117.     unsigned char *p;
  118.     short dir_num;
  119.     long x;
  120.  
  121.     if (n == 0) {
  122. #if unix
  123.         path[0] = '.';
  124.         path[1] = '\0';
  125. #else    
  126.         path[0] = '\0';
  127. #endif    
  128.         return path;
  129.     }
  130.     lseek(fd, hdr.dir_table_offset + n * sizeof(long), SEEK_SET);
  131.     Read(fd, &x, sizeof(x), 1);
  132.     lseek(fd, x, SEEK_SET);
  133.     Read(fd, buf, sizeof(buf), 0);
  134.     dir_num = buf[0] + (buf[1] << 8);
  135.     p = lookup_dir(dir_num);
  136.     strcat(p, "/");
  137.     strcat(p, buf + 2);
  138.     return p;
  139. }
  140.  
  141. static char *
  142. lookup_filename(long n) {
  143.     unsigned char buf[300];
  144.     unsigned char *p;
  145.     short dir_num;
  146.  
  147.     lseek(fd, n, SEEK_SET);
  148.     Read(fd, buf, sizeof(buf), 0);
  149.     dir_num = buf[0] + (buf[1] << 8);
  150.     p = lookup_dir(dir_num);
  151.     strcat(p, "/");
  152.     strcat(p, buf + 2);
  153.     return p;
  154. }
  155.  
  156. static int
  157. search_block(int block) {
  158.     int rv, i;
  159.     long *p;
  160.     long b[2];
  161.     int nfiles;
  162.  
  163. /*    fprintf(stderr, "searching_block( %d == %x )\n", block, block);  */
  164.     if (lseek(fd, hdr.block_table_offset + block * 4, SEEK_SET) < 0) {
  165.     fprintf(stderr, "lseek <1> failed: %s\n", strerror(errno));
  166.     exit(1);
  167.     }
  168.     Read(fd, &b, sizeof(b), 1);
  169.     if (block == (hdr.num_blocks - 1)) {
  170.         nfiles = hdr.num_files - b[0];
  171.     assert(nfiles > 0);
  172.     } else {
  173.         nfiles = b[1] - b[0];
  174.     assert(nfiles > 0);
  175.     }
  176.     p = malloc(nfiles * sizeof(*p));
  177.     if (lseek(fd, hdr.file_table_offset + (b[0] * 4), SEEK_SET) < 0) {
  178.     fprintf(stderr, "lseek <2> failed: %s\n", strerror(errno));
  179.     exit(1);
  180.     }
  181.     assert(lseek(fd, 0L, SEEK_CUR) ==
  182.            hdr.file_table_offset + (b[0] * 4));
  183.     Read(fd, p, nfiles * 4, 1);
  184.     for (rv = i = 0; i < nfiles; ++i) {
  185.  
  186. #ifndef unix
  187.     char dir[3];
  188.  
  189.     sprintf(dir, "%c:", getdisk() + 'A');
  190.         rv += search_file(get_real_filename(dir, lookup_filename(p[i])));
  191. #else
  192.         rv += search_file(lookup_filename(p[i]));
  193. #endif    
  194.     }
  195.     free(p);
  196.     return rv;
  197. }
  198.  
  199. static int
  200. search(unsigned long x) {
  201.     int rv;
  202.     unsigned char p[512];
  203.     int i, j, n, b;
  204.     long offset;
  205.  
  206.     rv = 0;
  207.     offset = x & 0xffffffL;
  208.     switch ((x >> 30) & 0x3) {
  209.  
  210.     case 0:
  211.         lseek(fd, offset, SEEK_SET);
  212.         Read(fd, p, sizeof(p), 0);
  213.         for (i = 0; i < hdr.num_blocks; ++i) {
  214.             if (p[i/8] & (1 << (i % 8))) {
  215.                 rv += search_block(i);
  216.             }
  217.         }
  218.         break;
  219.  
  220.     case 1:
  221.         rv = search_block(x & 0xfff);
  222.         break;
  223.  
  224.     case 2:
  225.         rv =  search_block(x & 0xfff);
  226.         rv += search_block((x >> 12) & 0xfff);
  227.         break;
  228.  
  229.     case 3:
  230.  
  231.         lseek(fd, offset, SEEK_SET);
  232.         Read(fd, p, sizeof(p), 0);
  233.         j = 0;
  234.         n = p[j++];
  235.         n += ((p[j] & 0x0f) << 8);
  236.         for (i = 1; i < n + 1; ++i) {
  237.             if (i & 1) {
  238.                 b = (p[j++] & 0xf0) >> 4;
  239.                 b += p[j++] << 4;
  240.             } else {
  241.                 b = p[j++];
  242.                 b += (p[j] & 0x0f) << 8;
  243.             }
  244.             rv += search_block(b);
  245.         }
  246.         break;
  247.     }
  248.     return rv;
  249. }
  250.  
  251. void
  252. main(int argc, char **argv) {
  253.     unsigned int len;
  254.     unsigned int match;
  255.     unsigned long h;
  256.     unsigned long x;
  257.     unsigned short i;
  258.  
  259.     if (argc != 2) {
  260.         fprintf(stderr,
  261.         "usage: lookup <word>\n"
  262.         "       Search a CDROM for all files containing\n"
  263.             "       the specified word.\n");
  264.         exit(1);
  265.     }
  266.     strcpy(word, argv[1]);
  267.     len = strlen(word);
  268.     for (i = 0; i < len; ++i) {
  269.         if (isupper(word[i])) {
  270.             word[i] = tolower(word[i]);
  271.         }
  272.     }
  273.     strcpy(datafileroot, "utils/");
  274.     if ((fd = open("utils/lookup.dat", O_RDONLY|O_BINARY)) < 0) {
  275.     fprintf(stderr, "Cannot open %s: %s.\n",
  276.         "utils/lookup.dat", strerror(errno));
  277.     fprintf(stderr,
  278.         "Cd to the root directory of the cdrom and try again.\n");
  279.     exit(1);
  280.     }
  281.  
  282.     Read(fd, &hdr, sizeof(hdr), 1);
  283.     assert(hdr.header_size == sizeof(hdr));
  284.     assert(hdr.filesize == lseek(fd, 0L, SEEK_END));
  285.     h = hash2(word);
  286.     match = 0;
  287.     for (i = 0;; ++i) {
  288.         lseek(fd, (h * 4) + hdr.hash_table_offset, SEEK_SET);
  289.         Read(fd, &x, sizeof(x), 1);
  290.         if (x == 0) {
  291.             break;
  292.         }
  293.         if (((x >> 30) == 1 && ((x >> 12) & 0xffff) == rehash16) ||
  294.             ((x >> 30) != 1 && ((x >> 24) & 0x003f) == rehash6)) {
  295.             match = search(x);
  296.             break;
  297.         }
  298.         h = (h + rehash6 + i) % hdr.hash_prime;
  299.     }
  300.     if (match == 0) {
  301.         printf("sorry, no match\n");
  302.     }
  303.     exit(match == 0);
  304. }
  305.  
  306. static void
  307. Read(int fd, void *buf, int n, int swap) {
  308.  
  309.     assert(n > 0);
  310.     assert(swap == 0 || (n & 3) == 0);
  311.     if (read(fd, buf, n) < 0) {
  312.         fprintf(stderr, "read failed: %s\n", strerror(errno));
  313.         exit(1);
  314.     }
  315. #ifdef sparc
  316.     if (swap) {
  317.         int i;
  318.         unsigned char c;
  319.         unsigned char *p;
  320.  
  321.         p = buf;
  322.         for (i = 0; i < n; i += 4) {
  323.             c = p[i];
  324.             p[i] = p[i + 3];
  325.             p[i + 3] = c;
  326.             c = p[i + 1];
  327.             p[i + 1] = p[i + 2];
  328.             p[i + 2] = c;
  329.         }
  330.     }
  331. #endif
  332.     return;
  333. }
  334.    
  335. #if defined(sparc) && ! defined(__svr4__)
  336. const char *
  337. strerror(error)
  338.     int error;
  339. {
  340.     static char defaultMsg[32];
  341.     extern int sys_nerr;
  342.     extern char *sys_errlist[];
  343.  
  344.     if ((error < sys_nerr) && (error > 0)) {
  345.         return sys_errlist[error];
  346.     }
  347.     (void) sprintf(defaultMsg, "unknown error (%d)", error);
  348.     return defaultMsg;
  349. }
  350. #endif
  351.  
  352.